<?php

class PDODB implements I_DAO {

    private $host;
    private $port;
    private $username;
    private $password;
    private $charset;
    private $dbname;

    private $dsn;
    private $driver_options;
    private $pdo;

    private static $instance;

    public static function getInstance($config)
    {
        if(!static::$instance instanceof static) {
            static::$instance = new static($config);
        }
        return static::$instance;
    }

    /**
     * PDODB constructor.
     * @param array $config
     */
    private function __construct($config)
    {
        $this->initParams($config); //初始化配置参数
        $this->initDSN();   //初始化DSN
        $this->initDriverOptions(); //初始化驱动选项
        $this->initPDO();   //初始化PDO对象
    }

    /**
     * 禁止克隆,保证单例对象
     */
    public function __clone(){}

    /**
     * 初始化配置参数
     * @param array $config 数据库配置数组
     */
    private function initParams($config) {
        $this->host = isset($config['host']) ? $config['host'] : 'localhost';
        $this->port = isset($config['port']) ? $config['port'] : '3306';
        $this->username = isset($config['username']) ? $config['username'] : 'root';
        $this->password = isset($config['password']) ? $config['password'] : '';
        $this->charset = isset($config['charset']) ? $config['charset'] : 'utf8';
        $this->dbname = isset($config['dbname']) ? $config['dbname'] : '';
    }

    /**
     * 初始化dsn
     */
    private function initDSN() {
        $this->dsn = "mysql:host=$this->host;port=$this->port;dbname=$this->dbname";
    }

    /**
     * 初始化驱动的Options
     */
    private function initDriverOptions() {
        $this->driver_options = array(
            PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES $this->charset",
        );
    }

    /**
     * 初始化PDO对象
     */
    private function initPDO() {
        $this->pdo = new PDO($this->dsn, $this->username, $this->password, $this->driver_options);
    }

    public function query($sql)
    {
        if(! $result = $this->pdo->query($sql)) {
            $error_info = $this->pdo->errorInfo();
            echo "<br />执行失败。";
            echo "<br />失败的sql语句为：" . $sql;
            echo "<br />出错信息为：" . $error_info[2];
            echo "<br />错误代号为：" . $error_info[1];
            die;
        }
        return $result;
    }

    public function getAll($sql)
    {
        $result = $this->query($sql);
        $list = $result->fetchAll(PDO::FETCH_ASSOC);
        //关闭游标(释放)
        $result->closeCursor();
        return $list;
    }

    public function getRow($sql)
    {
        $result = $this->query($sql);
        $row = $result->fetch(PDO::FETCH_ASSOC);
        $result->closeCursor();
        return $row;
    }

    public function getOne($sql)
    {
        $result = $this->query($sql);
        $string = $result->fetchColumn();
        $result->closeCursor();
        return $string;
    }

    /**
     * 转义用户数据，防止SQL注入
     * @param $data string 待转换字符串
     * @return string 转换后的字符串
     */
    public function escapeOneString($data)
    {
        return $this->pdo->quote($data);
    }

    public function escapeAllString($data)
    {
        foreach ($data as $key => $value) {
            $data[$key] = $this->escapeOneString($value);
        }
        return $data;
    }

    /**
     * 获取上一步insert操作产生的id
     */
    public function getInsertId()
    {
        return $this->pdo->lastInsertId();
    }

    public function getAffectRows()
    {
        return $this->pdo->rowCount();
    }
}